In concurrent programming (viz., interaction between multiple execution contexts such as threads, fibers (i.e., lightweight threads), and child processes), shared data is typically synchronized. When an execution context accesses data, it generally invokes a lock or other synchronization technique to ensure that no other execution context performs a conflicting access to the data. The synchronization prevents data from being corrupted but adds processing overhead to each data access. Perhaps more importantly, the synchronization often serializes the access to the data by different execution contexts. This serialization may inhibit the performance and scalability of a process, particularly where there are many independent processing resources that execute execution contexts.